﻿module Runner {
    export class Level extends Phaser.State {
        game: Phaser.Game;

        hero: Runner.Hero;

        tilemapURL: string;
        tilesURL: string;
        backgroundURL: string;
        parallaxBackgroundURL: string;
        tilemap: Phaser.Tilemap;
        tiles: Phaser.Image;
        enemyList: string[];

        enemyCollisionGroup: Phaser.Physics.P2.CollisionGroup;
        heroCollisionGroup: Phaser.Physics.P2.CollisionGroup;
        tileCollisiongGroup: Phaser.Physics.P2.CollisionGroup;

        background: Phaser.Sprite;
        parallaxBackground: Phaser.TileSprite;

        coins: Phaser.Physics.P2.CollisionGroup;
        coin: Runner.Coin;
        graphicLayer: Phaser.TilemapLayer;

        yOffset = 200;

        cameraPreviousX: number;
        loaded: boolean = false;

        battle: Battle;
        battleWith: Enemy[];
        enemyContacted: Enemy;

        constructor(tilemap: string, tiles: string, background: string, parallaxBackground?: string, enemyList?: string[]) {
            super();

            this.tilemapURL = tilemap;
            this.tilesURL = tiles;
            this.backgroundURL = background;
            this.parallaxBackgroundURL = parallaxBackground;

            if (!enemyList === undefined) {
                this.enemyList = enemyList;
            } else {
                this.enemyList = ['ArmoredOrc','Skeleton'];
            }
            
            
            
        }

        preload() {
            if (!this.loaded) {
                this.game.load.tilemap('level', this.tilemapURL, null, Phaser.Tilemap.TILED_JSON);
                this.game.load.image('platform_tiles', this.tilesURL, true);
                this.game.load.image('background', this.backgroundURL, true);

                if (this.parallaxBackgroundURL != null) {
                    this.game.load.image('parallaxBackground', this.parallaxBackgroundURL, true);
                }
            }
        }

        create() {
            if (!this.loaded) {

                this.background = this.game.add.sprite(0, 0, 'background');
                this.background.width = this.game.width;
                this.background.height = this.game.height;
                this.background.smoothed = false;
                this.background.fixedToCamera = true;

                if (this.parallaxBackgroundURL != null) {
                    this.parallaxBackground = this.game.add.tileSprite(0, this.yOffset, this.game.width, this.game.cache.getImage('parallaxBackground').height, 'parallaxBackground');
                    this.parallaxBackground.scale.x = this.parallaxBackground.scale.y;
                    this.parallaxBackground.fixedToCamera = true;
                }




                this.tilemap = this.game.add.tilemap('level', 32, 32);
                this.tilemap.addTilesetImage('Platform_Tiles', 'platform_tiles');
                this.graphicLayer = this.tilemap.createLayer('Platforms');
                var collision = this.tilemap.createLayer('Collisions');
                this.graphicLayer.resizeWorld();

                this.tilemap.setCollisionBetween(1, 100000, true, 'Collisions');
                var tileBody = this.game.physics.p2.convertTilemap(this.tilemap, collision);

                this.game.world.setBounds(0, 0, this.game.world.width, Runner.GAMEHEIGHT);

                this.enemyCollisionGroup = this.game.physics.p2.createCollisionGroup();
                this.heroCollisionGroup = this.game.physics.p2.createCollisionGroup();
                this.tileCollisiongGroup = this.game.physics.p2.createCollisionGroup();

                this.game.physics.p2.enableBody(this.tileCollisiongGroup, false);
                this.game.physics.p2.enableBody(this.enemyCollisionGroup, false);
                this.game.physics.p2.enableBody(this.heroCollisionGroup, false);
                this.game.physics.p2.updateBoundsCollisionGroup();

                tileBody.forEach(function (element) {
                    element.setCollisionGroup(this.tileCollisiongGroup);
                    element.collides([this.enemyCollisionGroup, this.heroCollisionGroup]);
                    this.game.physics.p2.enable(element);
                    this.game.physics.p2.enableBody(element, false);
                }, this);

                this.loadPlayer();
                this.loadEnemies();
                this.createCoins();



                this.hero.body.setCollisionGroup(this.heroCollisionGroup);
                this.hero.body.collides(this.tileCollisiongGroup);

                this.hero.body.collides(this.enemyCollisionGroup, this.playerHitEnemy, this);
                //this.hero.body.onBeginContact.add(this.playerHitEnemy, this.hero);
                this.hero.body.collideWorldBounds = true;
            }
            this.loaded = true;
        }

        loadPlayer() {
            var result = this.findObjectsByType('Player', this.tilemap, 'Characters');
            this.hero = new Hero(this.game, result[0].x, result[0].y);
            
            this.game.add.existing(this.hero);
        }

        loadEnemies() {
            var result = this.findObjectsByType('Enemy', this.tilemap, 'Characters');
            
            result.forEach(function (element) {
                var enemy = new Enemy(this.game, element.x, element.y,
                    this.enemyList[Math.floor(Math.random() * this.enemyList.length)], null, null, 250);
                enemy.body.setCollisionGroup(this.enemyCollisionGroup);
                enemy.body.collides([this.heroCollisionGroup, this.enemyCollisionGroup, this.tileCollisiongGroup]);

                this.game.add.existing(enemy);
            }, this);
        }

        createCoins() {
            var result = this.findObjectsByType('Item', this.tilemap, 'Coins');

            result.forEach(function (element) {
                this.coin = new Coin(this.game, element.x, element.y);
                this.coin.body.fixedRotation = true;
                this.coin.body.allowGravity = false;
                this.coin.body.immovable = true;

                this.game.add.existing(this.coin);
            }, this); 
        }

        playerHitEnemy(body1: Phaser.Physics.P2.Body, body2: Phaser.Physics.P2.Body) {
            if (this.battle === undefined || this.battle == null) { //Remove the double tap group
                var enemy = getSprite<Enemy>(this.game, body2);
                var numberOfEnemies = Math.floor(Math.random() * 4 + 1);
                var enemies: string[] = [];
                for (var i = 0; i < numberOfEnemies; i++) {
                    enemies.push(enemy.key.toString());
                }
                //console.log(enemies.length);
                
                this.enemyContacted = enemy;
                this.battle = new Battle(this.game, this.hero.key.toString(), enemies);
            }
        }

        findObjectsByType(type, map: Phaser.Tilemap, layer: string): any[] {
            var result = new Array();

            map.objects[layer].forEach(function (element) {
                if (element.properties.Type === type) {
                    element.y -= map.tileHeight;
                    result.push(element);
                }
            });
            return result;
        }

        createFromTiledObject(element, group: Phaser.Group) {
            var sprite = group.create(element.x, element.y, element.properties.sprite);

            Object.keys(element.properties).forEach(function (key) {
                sprite[key] = element.properties[key];
                console.log(element.properties[key]);
            });
        }

        update() {
            if (!inBattle(this.battle)) {
                if (this.parallaxBackgroundURL != null) {
                    this.parallaxBackground.tilePosition.x = -this.game.camera.x * 0.1;
                }

                this.graphicLayer.position.set(this.game.camera.x, this.game.camera.y + this.yOffset);
            } else {
                switch (this.battle.stateOf) {
                    case battleState.fail:
                        console.log('MUCH FAIL');
                        break;
                    case battleState.success:
                        if (this.enemyContacted != null || this.enemyContacted !== undefined) {
                            this.enemyContacted.destroy(true);
                        }

                        this.battle.destroy(true);

                        this.battle = null;

                        break;
                    case battleState.onGoing:
                    default:
                }
            }
        }
    }
}